package com.whately.core.base.config.aspect;

import com.whately.core.base.annotation.WhLog;
import com.whately.core.base.constant.ConstantProject;
import com.whately.core.base.constant.DebugSwitcher;
import com.whately.core.base.selfconfig.SelfDefineConfigWhLog;
import com.whately.core.base.utils.GsonUtils;
import lombok.extern.slf4j.Slf4j;
import org.apache.commons.lang3.StringUtils;
import org.aspectj.lang.ProceedingJoinPoint;
import org.aspectj.lang.annotation.Around;
import org.aspectj.lang.annotation.Aspect;
import org.aspectj.lang.annotation.Pointcut;
import org.aspectj.lang.reflect.MethodSignature;
import org.springframework.beans.factory.annotation.Autowired;
import org.springframework.boot.autoconfigure.condition.ConditionalOnExpression;
import org.springframework.context.annotation.Configuration;

import javax.servlet.http.HttpServletRequest;
import javax.servlet.http.HttpServletResponse;
import java.lang.reflect.Method;

/**
 * 日志log拦截器
 * 记录入口的日志信息
 * 打印描述信息及入参
 */
@Aspect
@Configuration
@ConditionalOnExpression("${myconfig.whlog.enable:true} && ${myconfig.whlog.pointCutCtrlSrv:true}!=false")
@Slf4j
public class WhLogAllAspect {

    @Autowired
    private DebugSwitcher debugSwitcher;

    @Autowired
    private SelfDefineConfigWhLog selfDefineConfigWhLog;

    @Pointcut("@annotation(com.whately.core.base.annotation.WhLog)")
    public void pointCut() {

    }

    @Pointcut(ConstantProject.GLOBAL_AOP_POINTCUT_EXPRESSION)
    public void pointCutServicePackage() {

    }

    @Pointcut("@annotation(org.springframework.web.bind.annotation.RequestMapping)"
            +"||@annotation(org.springframework.web.bind.annotation.PostMapping)"
            +"||@annotation(org.springframework.web.bind.annotation.GetMapping)")
    public void pointCutRequestMapping() {

    }


    @Around(value = "pointCut()||pointCutServicePackage()||pointCutRequestMapping()")
    public Object process(ProceedingJoinPoint point) throws Throwable {
        return dealLogAspect(point,debugSwitcher,selfDefineConfigWhLog);
    }

    public static Object dealLogAspect(ProceedingJoinPoint point,DebugSwitcher debugSwitcher,SelfDefineConfigWhLog selfDefineConfigWhLog) throws Throwable{
        //全局的日志打印开关
        boolean logOpen = selfDefineConfigWhLog.isOpen();
        if(!logOpen){
            //日志不打印,直接执行
            return point.proceed();
        }

        MethodSignature signature = (MethodSignature) point.getSignature();
        //String signatureName = signature.getName();
        Method method = signature.getMethod();



        WhLog whLog = method.getAnnotation(WhLog.class);
        String desc = null;
        boolean printParamInAnno = false;
        if(whLog!=null){
            desc = whLog.desc();
            printParamInAnno = whLog.printParams();
        }

        String className =point.getTarget().getClass().getName();
        String methodName = method.getName();

        boolean isPrintParam = selfDefineConfigWhLog.isOpenPrintParam();
        //执行之前打印入口日志
        log.info("LOG IN {} [ {} ] {}",className,methodName,desc==null?StringUtils.EMPTY:("desc = "+desc));

        //参数打印开关
        boolean print_param_flag_global;
        //生产环境默认关闭，其它默认打开
        if(debugSwitcher.isProfileLocalOrDev()){
            print_param_flag_global = true;

            if(isPrintParam==false){
                print_param_flag_global = false;
            }
        }else{
            print_param_flag_global = false;

            if(isPrintParam){
                print_param_flag_global = true;
            }
        }

        if(printParamInAnno||print_param_flag_global){
            StringBuilder sb = new StringBuilder();
            Object[] args = point.getArgs();
            for (Object object : args) {
                String tmp ;
                if(object==null){
                    tmp = "(null)";
                }else if(object instanceof HttpServletRequest){
                    tmp = "(request)";
                }else if(object instanceof HttpServletResponse){
                    tmp = "(response)";
                }else{
                    tmp = "("+ GsonUtils.toJsonString(object)+")";
                }
                if(sb.length()>0){
                    sb.append(", ");
                }
                sb.append(tmp);
            }

            log.info("LOGGING PARAM in [ {} ], length {} ,content is [{}] ",methodName,args.length,sb);
        }

        //执行
        Object result =  point.proceed();

        //执行结束打印日志
        //log.info("LOGGING OVER {} [ {} ]",className,methodName);
        return result;
    }

}
